﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Medianamik.Core
{
    public abstract class HierarchicalEntity<T> : Entity<T>, IHierarchicalEntity
        where T : IHierarchicalEntity
    {
        protected HierarchicalEntity()
        {
            
        }

        protected HierarchicalEntity(Guid id, Guid? parentId, string path, int? depth)
           : base(id)
        {
            _parentId = parentId;
            _path = path;
            _depth = depth;
        }

        private Guid? _parentId;
        public Guid? ParentID
        {
            get { return _parentId; }
            set
            {
                _parentId = value;
                if (Status != EntityStates.New)
                    Status = EntityStates.Dirty;
            }
        }

        private string _path;
        public string Path
        {
            get
            {
                if (_path == null)
                {
                    BuildPathAndDepth();
                }

                return _path;
            }
             set
            {
                _path = value;
            }
        }

        private int? _depth;
        public int Depth
        {
            get
            {
                if (_depth == null)
                {
                    BuildPathAndDepth();
                }

                return _depth.GetValueOrDefault(0);
            }
             set
            {
                _depth = value;
            }
        }

        private void BuildPathAndDepth()
        {
            string parentPath = ".";
            int parentDepth = -1;

            if (ParentID.HasValue)
            {
                parentPath = Parent.Path;
                parentDepth = Parent.Depth;
            }

            Path = string.Concat(parentPath, ID, ".");
            Depth = parentDepth + 1;
        }

        private T _parent;
        public T Parent
        {
            get
            {
                if (_parent == null)
                    _parent = GetParent(ParentID.Value);

                return _parent;
            }
        }

        protected abstract T GetParent(Guid parentId);
    }
}
